/*!
 * \file cicsts_comm.h
 *
 * \brief CICSTS模块共通文件
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.
 *
 * \version 1.0
 * \author songbb
 * \date 2016/04/22
 *
 */

#ifndef __CICSTS_COMM_H_
#define __CICSTS_COMM_H_

#include <sys/time.h>

#include "frlog.h"
#include "frreport_comm.h"

#include "cicsts_core.h"

#define APM_CICSTS_DBG 0              //!< CICSTS的Debug开关
#define APM_CICSTS_ENABLE_FRLOG 0     //!< FRLOG开关

#define APM_CICSTS_FLAG_UNSET -1      //!< 标识符变量的初始化值

#define APM_CICSTS_HASH_SIZE 100      //!< CICSTS模块哈希桶的最大尺寸

#define APM_CICSTS_PKT_REQ_HEADER_LEN 87  //!< 请求包通用头长度
#define APM_CICSTS_PKT_RESP_HEADER_LEN 26  //!< 响应包通用头长度

#define APM_DTS_REPORT_MODULE_NAME "dts"        //!< 数据上报模块名
#define APM_DTS_REPORT_REQ_SERVICE_NAME APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".service.name"      //!< 服务名或者程序名，例如to_upper
#define APM_DTS_REPORT_REQ_SERVICE_METHOD APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".service.method"  //!< call，commit,rollback,suspend,resume
#define APM_DTS_REPORT_REQ_ARG_SIZE APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".service.arg.size"      //!< 请求参数的个数
#define APM_DTS_REPORT_REQ_ARG_DATA APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".service.arg.1"         //!< 请求参数
#define APM_DTS_REPORT_RESP_ARG_SIZE APM_REPORT_KEY_RESP"."APM_DTS_REPORT_MODULE_NAME".service.return.size" //!< 响应参数的个数
#define APM_DTS_REPORT_RESP_ARG_DATA APM_REPORT_KEY_RESP"."APM_DTS_REPORT_MODULE_NAME".service.return.1"    //!< 响应参数

#define KRED        "\x1B[0;31m"    //!< ANSI红色
#define KSALMON     "\x1B[1;31m"    //!< ANSI鲑红色
#define KGREEN      "\x1B[0;32m"    //!< ANSI绿色
#define KLIMEGREEN  "\x1B[1;32m"    //!< ANSI青柠色
#define KYELLOW     "\x1B[0;33m"    //!< ANSI黄色
#define KORANGE     "\x1B[0;34m"    //!< ANSI橘黄色
#define KBLUE       "\x1B[1;34m"    //!< ANSI蓝色
#define KMAGENTA    "\x1B[0;35m"    //!< ANSI洋红色
#define KPINK       "\x1B[1;35m"    //!< ANSI粉色
#define KCYAN       "\x1B[0;36m"    //!< ANSI青色
#define RESET       "\x1B[0m"       //!< ANSI颜色重置

#if APM_CICSTS_DBG
    #define CICSTS_PRINT(...) printf(__VA_ARGS__)                         //!< 普通的打印
    #define CICSTS_PRINT_DETAIL(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(__VA_ARGS__))                            //!< 打印Detail
    #define CICSTS_PRINT_DBG(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KGREEN),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印debug
    #define CICSTS_PRINT_FATAL(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KORANGE),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印fatal
    #define CICSTS_PRINT_EMERG(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KRED),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印emergent
    #define CICSTS_PRINT_ALERT(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KSALMON),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印alert
    #define CICSTS_PRINT_CRIT(...) (printf("[%s, Line:%u, %s()]",\
                            __FILE__,__LINE__,__func__),\
                            printf(KMAGENTA),\
                            printf(" "__VA_ARGS__),\
                            printf(RESET))                              //!< 打印critical
    #define CICSTS_PRINT_ERR(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KPINK),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印error
    #define CICSTS_PRINT_WARN(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KYELLOW),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印warning
    #define CICSTS_PRINT_NOTICE(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KLIMEGREEN),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印notice
    #define CICSTS_PRINT_INFO(...) (printf("[%s, Line:%u, %s()]",\
                            __FILE__,__LINE__,__func__),\
                            printf(KBLUE),\
                            printf(" "__VA_ARGS__),\
                            printf(RESET))                              //!< 打印info
    #define PRINT_HEX_STRING(a,b,c) (printf("[%s, Line:%u, %s()] ",\
                            __FILE__,__LINE__,__func__),\
                            printf(KCYAN),\
                            printf(a":["),cicsts_print_hex_string(b,c),printf("]\n"),\
                            printf(RESET))                              //!< 打印十六进制字符串
    #define CICSTS_PRINT_PACKET_SPECIFIED(tag, packet, offset, len) (printf("[%s, Line:%u, %s()] ",\
                            __FILE__,__LINE__,__func__),\
                            printf(KORANGE),\
                            printf(tag":["),cicsts_print_packet_specified(packet,offset,len),printf("]\n"),\
                            printf(RESET))                              //!< 以十六进制形式打印数据包的指定位置开始的数据
    #define CICSTS_PRINT_PACKET_CURRENT(a,b) (printf("[%s, Line:%u, %s()] ",\
                            __FILE__,__LINE__,__func__),\
                            printf(KCYAN),\
                            printf(a":["),cicsts_print_packet_current(b),printf("]\n"),\
                            printf(RESET))                              //!< 以十六进制打印数据包当前位置开始的数据
    #define CICSTS_PRINT_PACKET(a,b) (printf("[%s, Line:%u, %s()] ",\
                            __FILE__,__LINE__,__func__),\
                            printf(KCYAN),\
                            printf(a":["),cicsts_print_packet(b),printf("]\n"),\
                            printf(RESET))                              //!< 以十六禁止打印整个数据包
    #define CICSTS_PRINT_TIMEVAL(a,b) (printf("[%s, Line:%u, %s()]",\
                            __FILE__,__LINE__,__func__),\
                            printf(KGREEN),\
                            printf(" %s", a), \
                             cicsts_print_timeval(b),\
                             printf(RESET))                             //!< 打印timeval
#else
    #define CICSTS_PRINT(...)
    #define CICSTS_PRINT_DETAIL(...)
    #define CICSTS_PRINT_DBG(...)
    #define CICSTS_PRINT_FATAL(...)
    #define CICSTS_PRINT_EMERG(...)
    #define CICSTS_PRINT_ALERT(...)
    #define CICSTS_PRINT_CRIT(...)
    #define CICSTS_PRINT_ERR(...)
    #define CICSTS_PRINT_WARN(...)
    #define CICSTS_PRINT_NOTICE(...)
    #define CICSTS_PRINT_INFO(...)
    #define PRINT_HEX_STRING(a,b,c)
    #define CICSTS_PRINT_PACKET_SPECIFIED(tag, packet, offset, len)
    #define CICSTS_PRINT_PACKET_CURRENT(a,b)
    #define CICSTS_PRINT_PACKET(a,b)
    #define CICSTS_PRINT_TIMEVAL(a,b)
#endif

#if APM_CICSTS_ENABLE_FRLOG
    #define CICSTS_FRLOG_ERROR(...) FRLOG_ERROR_DETAIL(...)               //!< 打印Log日志
#else
#define CICSTS_FRLOG_ERROR(...)
#endif

#define CICSTS_MALLOCK_ERR CICSTS_PRINT_EMERG("can not malloc memory\n"); \
                          FRLOG_ERROR_DETAIL("can not malloc memory");  //!< malloc执行出错记录

/*!
 * 释放内存
 *
 * \param pp_buffer  (内存两重指针)
 *
 */
void cicsts_free(void **pp_buffer);

/*!
 * 打印时间戳
 *
 * \param st_timestamp  (时间戳)
 *
 */
void cicsts_print_timeval(struct timeval st_timestamp);

/*!
 * 格式化成十六进制字符串
 *
 * \param p_inbuff  (输入的字符串)
 * \param i_len     (输入的字符串长度)
 * \param p_outbuff (格式化后的十六进制字符串)
 *
 */
void cicsts_bin_to_hex_string(char *p_inbuff
                            , int i_len
                            , char *p_outbuff);

/*!
 * 按一个字节打印十六进行字符串
 *
 * \param p_buff    (输入的字符串)
 * \param i_len     (输入的字符串长度)
 *
 */
void cicsts_print_hex_string(char *p_buff
                        , int i_len);

/*!
 * 打印指定位置的包内容
 *
 * \param p_st_cicsts_packet      (CICSTS数据包)
 * \param i_pos                 (开始位置)
 * \param i_len                 (长度)
 *
 */
void cicsts_print_packet_specified(L7_cicsts_packet *p_st_cicsts_packet
                                , int i_pos
                                , int i_len);

/*!
 * 打印当前位置开始的包内容
 *
 * \param p_st_cicsts_packet      (CICSTS数据包)
 *
 */
void cicsts_print_packet_current(L7_cicsts_packet *p_st_cicsts_packet);

/*!
 * 打印整个包内容
 *
 * \param p_st_cicsts_packet      (CICSTS数据包)
 *
 */
void cicsts_print_packet(L7_cicsts_packet *p_st_cicsts_packet);

/*!
 * 判断是否处于分片包状态
 *
 * \param p_st_cicsts_packet      (CICSTS数据包)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
int cicsts_packet_is_in_fragment(L7_cicsts_packet *p_st_cicsts_packet);

/*!
 * 释放 L7_trans_stmt
 *
 * \param **pp_st_stmt      (L7_trans_stmt)
 *
 */
void cicsts_free_stmt(L7_cicsts_stmt **pp_st_stmt);

/*!
 * 释放 stmt node节点
 *
 * \param *p_st_node      (Frlist_node)
 *
 */
void cicsts_stmt_node_free(Frlist_node *p_st_node);

/*!
 * 上报请求信息
 *
 * \param p_st_conn         (ct信息)
 * \param p_st_cicsts_packet  (CICSTS数据包)
 * \param p_st_body         (数据上报体内容)
 * \param p_st_hash_report  (数据上报用)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
int cicsts_report_msg_data_req(Conntrack *p_st_conn
                            , L7_cicsts_packet *p_st_cicsts_packet
                            , Frreport_body_data *p_st_body
                            , Frhash_header *p_st_hash_report
                            , L7_cicsts_stmt *p_st_stmt);

/*!
 * 上报响应信息
 *
 * \param p_st_conn         (ct信息)
 * \param p_st_cicsts_packet  (CICSTS数据包)
 * \param p_st_body         (数据上报体内容)
 * \param p_st_hash_report  (数据上报用)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
int cicsts_report_msg_data_resp(Conntrack *p_st_conn
                                , L7_cicsts_packet *p_st_cicsts_packet
                                , Frreport_body_data *p_st_body
                                , Frhash_header *p_st_hash_report);

#endif
